package com.itheima.spring.cyclicDependency2.main;

import com.itheima.spring.cyclicDependency2.bean.OrderService;
import com.itheima.spring.cyclicDependency2.bean.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 模拟循环依赖
 */
public class MainClass1 {

    public static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    //一级缓存
    public static Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    //模拟注册BeanDefinition
    public static void loadBeanDefinitionMap() {
        BeanDefinition bd1 = new RootBeanDefinition(UserService.class);
        BeanDefinition bd2 = new RootBeanDefinition(OrderService.class);
        beanDefinitionMap.put("userService", bd1);
        beanDefinitionMap.put("orderService", bd2);
    }

    public static void main(String[] args) {
        loadBeanDefinitionMap();
        beanDefinitionMap.forEach((beanName, beanDefinition) -> {
            try {
                Object bean = getBean(beanName);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    public static Object getBean(String beanName) throws Exception {
        //创建bean
        RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
        Class<?> beanClass = beanDefinition.getBeanClass();
        Object instanceBean = beanClass.newInstance();

        //填充属性
        Field[] declaredFields = beanClass.getDeclaredFields();
        for (Field f : declaredFields) {
            Autowired autowired = f.getAnnotation(Autowired.class);
            if (autowired != null) {
                //从Spring 获取依赖对象
                Object object = getBean(f.getName());
                f.set(instanceBean, object);
            }
        }

        //初始化 略

        //添加到单例池
        singletonObjects.put(beanName, instanceBean);

        return instanceBean;
    }
}
